package de.mhus.lib.mandala.impl;

import java.io.PrintWriter;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;

import de.mhus.lib.core.MString;
import de.mhus.lib.core.base.IgnoreBind;
import de.mhus.lib.mandala.Element;
import de.mhus.lib.mandala.Response;
import de.mhus.lib.mandala.TagAttributes;
import de.mhus.lib.mandala.UiUtil;
import de.mhus.lib.mandala.Window;

@IgnoreBind
public class DefaultResponse extends Response {

	protected PrintWriter out;
	protected HashMap<String, Element> attributes = new HashMap<String, Element>();

	public DefaultResponse(Window window, PrintWriter out) {
		super(window);
		this.out = out;
	}

	@Override
	public void println(String text) {
		out.println(text);
	}

	@Override
	public void startTag(String name, String clazz, boolean single,
			boolean inline, TagAttributes tag, String... attributes) {

		out.print("<");
		out.print(name);
		
		renderTag(name, clazz, tag, attributes);
		
		if (single) out.print("/");
		out.print(">");
		if (!inline) out.println();
		
	}

	protected void renderTag(String name, String clazz, TagAttributes tag, String[] attributes) {
		
		String dataBind = null;
		String type = null;
		if (attributes != null) {
			for (int i = 0; i < attributes.length; i+=2) {
				if (attributes.length > i+1) {
					if (attributes[i] != null && attributes[i+1] != null) {
						if (attributes[i].equals("data-bind")) {
							dataBind = dataBind == null ? attributes[i+1] : dataBind + ',' + attributes[i+1];
						} else {
							if (attributes[i].equals("type"))
								type = attributes[i+1];
							out.print(' ');
							out.print(attributes[i]);
							out.print("='");
							out.print(attributes[i+1]);
							out.print('\'');
						}
					}
				}
			}
		}

		
		if (tag != null) {
			
			TagAttributes.EMPHASIS emphasisStyle = tag.getEmphasis();
			String emphasisBase = tag.getStyleBase();
			if (emphasisStyle != null) {
				if (emphasisBase == null)
					emphasisBase = emphasisStyle.toString().toLowerCase();
				else
					emphasisBase = emphasisBase + "-" + emphasisStyle.toString().toLowerCase();
				if (clazz == null)
					clazz = emphasisBase;
				else
					clazz = clazz + " " + emphasisBase;
			}
			
			TagAttributes.SIZE sizeStyle = tag.getSizeStyle();
			String sizeBase = tag.getStyleBase();
			if (sizeStyle != null && sizeStyle != TagAttributes.SIZE.DEFAULT) {
				if (sizeBase == null)
					sizeBase = sizeStyle.toString().toLowerCase();
				else
					sizeBase = sizeBase + "-" + sizeStyle.toString().toLowerCase();
				if (clazz == null)
					clazz = sizeBase;
				else
					clazz = clazz + " " + sizeBase;
			}

			clazz = tag.findStyleClass(clazz);

		}
		
		if (clazz != null) {
			print(" class=\"");print(clazz);print("\"");
		}
		
		if (tag != null) {
			if (MString.isSet(tag.getExtraStyle())) {
				print(" style=\"");print(tag.getExtraStyle());print("\"");
			}
			tag.renderDataBind(this, dataBind,name,type);
		}
		
	}

	@Override
	public void endTag(String name, boolean inline) {
			out.print("</");
			out.print(name);
			out.print(">");
			if (!inline) out.println();
	}

	@Override
	public void print(String text) {
		out.print(text);
	}

	@Override
	public void registerElement(Element value) {
		if (!attributes.containsKey(value.getId()))
			attributes.put(value.getId(), value);
	}

	@SuppressWarnings("unchecked")
	@Override
	public void renderAttributes() {
		out.println("<script type='text/javascript'>");
		out.print("var "+getWindow().getId()+" = {");
		
		boolean first =true;
		boolean written =true;
		HashSet<String> alreadyDone = new HashSet<String>();
		
		do {
			written = false;
			for (Map.Entry<String, Element> item : attributes.entrySet().toArray(new Map.Entry[0]) ) {
				if (!alreadyDone.contains(item.getKey())) {
					alreadyDone.add(item.getKey());
					written = true;
					if (item.getValue().needFunctionImplementation()) {
						if (!first) out.print(',');
						out.print('\n');
						out.print(item.getKey());
						out.print(':');
						item.getValue().doRender(getWindow(),this);
						first = false;
					} else
					if (getWindow().getUi().isDebugFunctions()) {
						out.print("// '");
						out.print(item.getValue().getId());
						out.println("' not implemented");
						
					}
				}
				out.println();
			}
		} while (written);
		
		out.println("};\nko.applyBindings("+getWindow().getId()+");");
		UiUtil.renderAsGetter(getWindow().getInitialAction(), getWindow(), this);
		out.println("</script>");
		
	}

}
